 /*******************************************************************************
  * Copyright (c) 2000, 2004 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/cpl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  *******************************************************************************/

 package org.eclipse.ui.internal.commands;

 import java.io.IOException ;
 import java.io.Reader ;
 import java.io.StringReader ;
 import java.io.StringWriter ;
 import java.io.Writer ;
 import java.util.Collections ;
 import java.util.List ;

 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.util.IPropertyChangeListener;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.ui.IMemento;
 import org.eclipse.ui.WorkbenchException;
 import org.eclipse.ui.XMLMemento;

 /**
  * The persistent store for the preferences related to the commands
  * infrastructure. This store handles loading and storing of preferences.
  *
  * @since 3.0
  */
 public final class PreferenceCommandRegistry extends
         AbstractMutableCommandRegistry {

     /**
      * The full package name for the store.
      */
     private final static String KEY = Persistence.PACKAGE_FULL;

     /**
      * The underlying preference store. This value will never be
      * <code>null</code>.
      */
     private IPreferenceStore preferenceStore;

     /**
      * Constructs a new instance of <code>PreferenceCommandRegistry</code>
      * with the preference store it is supposed to use.
      *
      * @param preferenceStore
      * The preference store to use; must not be <code>null</code>.
      */
     public PreferenceCommandRegistry(IPreferenceStore preferenceStore) {
         if (preferenceStore == null) throw new NullPointerException ();

         this.preferenceStore = preferenceStore;

         this.preferenceStore
                 .addPropertyChangeListener(new IPropertyChangeListener() {

                     public void propertyChange(
                             PropertyChangeEvent propertyChangeEvent) {
                         if (KEY.equals(propertyChangeEvent.getProperty())) try {
                             load();
                         } catch (final IOException e) {
                             e.printStackTrace();
                         }
                     }
                 });

         try {
             load();
         } catch (IOException eIO) {
             // At least we tried....
 }
     }

     /**
      * Loads all of the preferences from the store, and sets member variables
      * containing all of the values.
      *
      * @throws IOException
      * If something happens while trying to read the store.
      */
     public void load() throws IOException {
         String preferenceString = preferenceStore.getString(KEY);

         if (preferenceString != null && preferenceString.length() != 0) {
             Reader reader = new StringReader (preferenceString);

             try {
                 IMemento memento = XMLMemento.createReadRoot(reader);
                 List activeKeyConfigurationDefinitions = Collections
                         .unmodifiableList(Persistence
                                 .readActiveKeyConfigurationDefinitions(
                                         memento,
                                         Persistence.TAG_ACTIVE_KEY_CONFIGURATION,
                                         null));
                 List categoryDefinitions = Collections
                         .unmodifiableList(Persistence.readCategoryDefinitions(
                                 memento, Persistence.TAG_CATEGORY, null));
                 List commandDefinitions = Collections
                         .unmodifiableList(Persistence.readCommandDefinitions(
                                 memento, Persistence.TAG_COMMAND, null));
                 List keyConfigurationDefinitions = Collections
                         .unmodifiableList(Persistence
                                 .readKeyConfigurationDefinitions(memento,
                                         Persistence.TAG_KEY_CONFIGURATION, null));
                 List keySequenceBindingDefinitions = Collections
                         .unmodifiableList(Persistence
                                 .readKeySequenceBindingDefinitions(memento,
                                         Persistence.TAG_KEY_SEQUENCE_BINDING,
                                         null));
                 boolean commandRegistryChanged = false;

                 if (!activeKeyConfigurationDefinitions
                         .equals(this.activeKeyConfigurationDefinitions)) {
                     this.activeKeyConfigurationDefinitions = activeKeyConfigurationDefinitions;
                     commandRegistryChanged = true;
                 }

                 if (!categoryDefinitions.equals(this.categoryDefinitions)) {
                     this.categoryDefinitions = categoryDefinitions;
                     commandRegistryChanged = true;
                 }

                 if (!commandDefinitions.equals(this.commandDefinitions)) {
                     this.commandDefinitions = commandDefinitions;
                     commandRegistryChanged = true;
                 }

                 if (!keyConfigurationDefinitions
                         .equals(this.keyConfigurationDefinitions)) {
                     this.keyConfigurationDefinitions = keyConfigurationDefinitions;
                     commandRegistryChanged = true;
                 }

                 if (!keySequenceBindingDefinitions
                         .equals(this.keySequenceBindingDefinitions)) {
                     this.keySequenceBindingDefinitions = keySequenceBindingDefinitions;
                     commandRegistryChanged = true;
                 }

                 if (commandRegistryChanged) fireCommandRegistryChanged();
             } catch (WorkbenchException eWorkbench) {
                 throw new IOException ();
             } finally {
                 reader.close();
             }
         }
     }

     /**
      * Saves all of the preferences to the preference store.
      *
      * @throws IOException
      * If something happens while trying to write to the preference
      * store.
      */
     public void save() throws IOException {
         XMLMemento xmlMemento = XMLMemento.createWriteRoot(KEY);
         Persistence.writeActiveKeyConfigurationDefinitions(xmlMemento,
                 Persistence.TAG_ACTIVE_KEY_CONFIGURATION,
                 activeKeyConfigurationDefinitions);
         Persistence.writeCategoryDefinitions(xmlMemento,
                 Persistence.TAG_CATEGORY, categoryDefinitions);
         Persistence.writeCommandDefinitions(xmlMemento,
                 Persistence.TAG_COMMAND, commandDefinitions);
         Persistence.writeKeyConfigurationDefinitions(xmlMemento,
                 Persistence.TAG_KEY_CONFIGURATION, keyConfigurationDefinitions);
         Persistence.writeKeySequenceBindingDefinitions(xmlMemento,
                 Persistence.TAG_KEY_SEQUENCE_BINDING,
                 keySequenceBindingDefinitions);
         Writer writer = new StringWriter ();

         try {
             xmlMemento.save(writer);
             preferenceStore.setValue(KEY, writer.toString());
         } finally {
             writer.close();
         }
     }
 }

